package com.kly.user.task.v2.adjust;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.net.NetUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.fqgj.common.api.Response;
import com.fqgj.common.utils.CollectionUtils;
import com.fqgj.common.utils.DateUtil;
import com.fqgj.log.factory.LogFactory;
import com.fqgj.log.interfaces.Log;
import com.google.api.client.util.Lists;
import com.google.common.collect.Maps;
import com.kly.dto.TOrderDto;
import com.kly.service.TOrderService;
import com.kly.user.db.dao.UserDao;
import com.kly.user.db.dao.UserMsgSendTotalDao;
import com.kly.user.db.dao.UserTaskDetailDao;
import com.kly.user.db.dao.UserTaskJobDao;
import com.kly.user.db.dbo.PaidOrderDBO;
import com.kly.user.db.entity.UserEntity;
import com.kly.user.db.entity.UserTaskDetailEntity;
import com.kly.user.enums.AdjustEventDefType;
import com.kly.user.enums.UserStatus;
import com.kly.user.service.AdjustService;
import com.kly.user.task.enums.TaskTypeEnum;
import com.kly.user.utils.LittleOrangeService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * adjust事件推送
 * @author linqu
 */
@Service
public class PushToAdjustRetryTask {

    private static Log logger = LogFactory.getLog(PushToAdjustRetryTask.class);
    private String localIP = NetUtil.getLocalhostStr();

    @NacosValue(value = "${task.job.executor.ip}", autoRefreshed = true)
    private String taskJobExecutor;
    @NacosValue(value = "${push.to.ad.switch:true}", autoRefreshed = true)
    private Boolean pushToAdSwitch;
    @Resource
    private UserTaskDetailDao userTaskDetailDao;
    @Resource
    private UserMsgSendTotalDao userMsgSendTotalDao;
    @Resource
    private UserTaskJobDao userTaskJobDao;
    @Resource
    TOrderService tOrderService;
    @Resource
    AdjustService adjustService;
    @Resource
    UserDao userDao;


    /**
     * 执行频率：10分钟
     */
    @Scheduled(fixedDelay = 1000 * 120)
    public void run() {
        logger.info("====PushToAdjustRetryTask start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============PushToAdjustRetryTask, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAdSwitch) {
            logger.info("=============PushToAdjustRetryTask, pushToAfSwitch:{}", pushToAdSwitch);
            return;
        }

        pushToAdjust();
    }

    /**
     * 执行频率：10分钟
     */
    @Scheduled(fixedDelay = 1000 * 120)
    public void addDataToPool() {
        logger.info("====addDataToPool start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============addDataToPool, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAdSwitch) {
            logger.info("=============addDataToPool, pushToAfSwitch:{}", pushToAdSwitch);
            return;
        }


        // 获取已存在的事件数据集合
        final Map<String, List<String>> existsTaskLatestDayMap = getExistsTaskLatestDay();

        // 添加注册事件
        final List<UserEntity> userEntities = userDao.listUsersLatestDayAdjust();
        if (CollectionUtils.isEmpty(userEntities)) {
            return;
        }
        for (UserEntity user : userEntities) {
            if (UserStatus.ACTIVE.getType() != user.getStatus()) {
                logger.info("====无效用户===userCode:{}", user.getUserCode());
                continue;
            }
            final List<String> existsUsers = existsTaskLatestDayMap.get(AdjustEventDefType.Registration.getEventCode());
            if (CollectionUtils.isEmpty(existsUsers) || !existsUsers.contains(user.getUserCode())) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("userCode", user.getUserCode());
                adjustService.asyncTraceEvent(AdjustEventDefType.Registration, params);
            }
        }

        // 添加支付事件
        final List<PaidOrderDBO> paidOrderDBOS = userTaskDetailDao.listAllPaidOrdersLatestDay();
        if (CollectionUtils.isEmpty(paidOrderDBOS)) {
            return;
        }
        addPaidOrderToTaskDetail(existsTaskLatestDayMap, paidOrderDBOS);

    }

    private void addPaidOrderToTaskDetail(Map<String, List<String>> existsTaskLatestDayMap, List<PaidOrderDBO> paidOrderDBOS) {
        for (PaidOrderDBO dbo : paidOrderDBOS) {
            // 添加购买
            final List<String> purchaseOrders = existsTaskLatestDayMap.get(AdjustEventDefType.Purchase.getEventCode());
            if (CollectionUtils.isEmpty(purchaseOrders) || !purchaseOrders.contains(dbo.getOrderNo())) {
                addTaskDetail(dbo, AdjustEventDefType.Purchase);
            }


            // d0购买
            if (dbo.getTodayPaidFlag() == 1) {
                final List<String> orders = existsTaskLatestDayMap.get(AdjustEventDefType.D0_Purchase.getEventCode());
                if (CollectionUtils.isEmpty(orders) || !orders.contains(dbo.getOrderNo())) {
                    addTaskDetail(dbo, AdjustEventDefType.D0_Purchase);
                }

                final List<String> d0Users = existsTaskLatestDayMap.get(AdjustEventDefType.D0_Purchase_People.getEventCode());
                if (CollectionUtils.isEmpty(d0Users) || !d0Users.contains(dbo.getUserCode())) {
                    addTaskDetail(dbo, AdjustEventDefType.D0_Purchase_People);
                }
            }
        }
    }

    private void addTaskDetail(PaidOrderDBO dbo, AdjustEventDefType event) {
        final HashMap<String, Object> params = Maps.newHashMap();
        params.put("amount", dbo.getPaidAmount().multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP));
        params.put("productCode", dbo.getProductCode());
        params.put("userCode", dbo.getUserCode());
        params.put("orderNo", dbo.getOrderNo());
        adjustService.asyncTraceEvent(event, params);
    }




    private Map<String, List<String>> getExistsTaskLatestDay() {
        final List<UserTaskDetailEntity> userTaskDetailEntities = userTaskDetailDao.listAllTaskLatestDay(TaskTypeEnum.PUSH_DATA_TO_AD_JUST.getCode());
        if (CollectionUtils.isEmpty(userTaskDetailEntities)) {
            return Maps.newHashMap();
        }

        List<String> d0PurchaseList = userTaskDetailEntities.parallelStream().filter(o -> AdjustEventDefType.D0_Purchase.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("orderNo");
            }
            return "";
        }).collect(Collectors.toList());

        List<String> purchaseList = userTaskDetailEntities.parallelStream().filter(o -> AdjustEventDefType.Purchase.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("orderNo");
            }
            return "";
        }).collect(Collectors.toList());
        List<String> d0PurchasePeopleList = userTaskDetailEntities.parallelStream().filter(o -> AdjustEventDefType.D0_Purchase_People.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("userCode");
            }
            return "";
        }).collect(Collectors.toList());
        List<String> registerList = userTaskDetailEntities.parallelStream().filter(o -> AdjustEventDefType.Registration.getEventCode().equals(o.getExtend())).map(o -> {
            String request = o.getRequest();
            if (StringUtils.isNotBlank(request)) {
                return JSONObject.parseObject(request).getString("userCode");
            }
            return "";
        }).collect(Collectors.toList());

        Map<String, List<String>> paidOrdersMap = Maps.newHashMap();

        if (CollectionUtils.isNotEmpty(d0PurchaseList)) {
            paidOrdersMap.put(AdjustEventDefType.D0_Purchase.getEventCode(), d0PurchaseList);
        }
        if (CollectionUtils.isNotEmpty(purchaseList)) {
            paidOrdersMap.put(AdjustEventDefType.Purchase.getEventCode(), purchaseList);
        }
        if (CollectionUtils.isNotEmpty(d0PurchasePeopleList)) {
            paidOrdersMap.put(AdjustEventDefType.D0_Purchase_People.getEventCode(), d0PurchasePeopleList);
        }
        if (CollectionUtils.isNotEmpty(registerList)) {
            paidOrdersMap.put(AdjustEventDefType.Registration.getEventCode(), registerList);
        }

        return paidOrdersMap;
    }


    /**
     * 执行频率：10分钟
     */
//    @Scheduled(fixedDelay = 60000 * 10)
    public void pushD0_Order() {
        logger.info("====PushToAdjustRetryTask.pushD0_Order start");
        if (!taskJobExecutor.contains(localIP)) {
            logger.info("=============PushToAdjustRetryTask, currentLocalAddress:{}, onlyExecuteTaskIn:{}", localIP, taskJobExecutor);
            return;
        }
        if (!pushToAdSwitch) {
            logger.info("=============PushToAdjustRetryTask, pushToAfSwitch:{}", pushToAdSwitch);
            return;
        }

        // 查询近一小时内支付完成的数据
        final Response<List<TOrderDto>> response = tOrderService.listPaidOrder();
        if (response == null || !response.isSuccess()) {
            return;
        }
        final List<TOrderDto> orderList = response.getData();
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        // 添加d0购买订单数据
        addOrderToTaskPool_d0(filterOrderExistsInTaskDetail(orderList, AdjustEventDefType.D0_Purchase));
        // 添加d0购买用户数据
        addUserToTaskPool(filterUserExistsInTaskDetail(orderList, AdjustEventDefType.D0_Purchase_People));
        // 添加购买订单数据
        addOrderToTaskPool_all(filterOrderExistsInTaskDetail(orderList, AdjustEventDefType.Purchase));
    }

    /**
     * 获取待推送的订单
     */
    private List<TOrderDto> filterOrderExistsInTaskDetail(List<TOrderDto> orderList, AdjustEventDefType adjustEventDefType) {
        List<TOrderDto> newOrderList = Lists.newArrayList();
        newOrderList.addAll(orderList);

        // 获取近两小时d0推送数据
        final List<String> existsOrderNos = getOderNoList(2, adjustEventDefType.getEventCode());

        // 过滤已经存在的推送记录
        this.orderFilter(newOrderList, existsOrderNos);

        return newOrderList;
    }

    /**
     * 获取待推送的订单
     */
    private List<TOrderDto> filterUserExistsInTaskDetail(List<TOrderDto> orderList, AdjustEventDefType adjustEventDefType) {
        List<TOrderDto> newOrderList = Lists.newArrayList();
        newOrderList.addAll(orderList);

        // 获取近两小时d0推送数据
        final List<String> existsUsers = getUserCodeList(2, adjustEventDefType.getEventCode());

        // 过滤已经存在的推送记录
        this.userFilter(newOrderList, existsUsers);

        return newOrderList;
    }

    /**
     * 添加待推送数据到推送池中
     */
    private void addOrderToTaskPool_d0(List<TOrderDto> orderList) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        orderList.forEach(o -> {
            final UserEntity user = userDao.selectByUserCode(o.getUserCode());
            if (user != null && StringUtils.isNotBlank(user.getAdId())) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("amount", o.getPayableAmount().multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP));
                params.put("productCode", o.getProductCode());
                params.put("userCode", o.getUserCode());
                params.put("orderNo", o.getOrderNo());
                // 推送d0购买数据
                if (DateUtil.getDate(user.getGmtCreate(), DatePattern.NORM_DATE_PATTERN).equals(DateUtil.getDate(o.getPaidDate()))) {
                    adjustService.asyncTraceEvent(AdjustEventDefType.D0_Purchase, params);
                }
            }
        });
    }

    /**
     * 添加待推送数据到推送池中
     */
    private void addOrderToTaskPool_all(List<TOrderDto> orderList) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        orderList.forEach(o -> {
            final UserEntity user = userDao.selectByUserCode(o.getUserCode());
            if (user != null && StringUtils.isNotBlank(user.getAdId())) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("amount", o.getPayableAmount().multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP));
                params.put("productCode", o.getProductCode());
                params.put("userCode", o.getUserCode());
                params.put("orderNo", o.getOrderNo());
                adjustService.asyncTraceEvent(AdjustEventDefType.Purchase, params);
            }
        });
    }

    /**
     * 添加待推送数据到推送池中
     */
    private void addUserToTaskPool(List<TOrderDto> orderList) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }

        orderList.forEach(o -> {
            final UserEntity user = userDao.selectByUserCode(o.getUserCode());
            if (user != null && StringUtils.isNotBlank(user.getAdId())) {
                final HashMap<String, Object> params = Maps.newHashMap();
                params.put("amount", o.getPayableAmount().multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_HALF_UP));
                params.put("productCode", o.getProductCode());
                params.put("userCode", o.getUserCode());
                params.put("orderNo", o.getOrderNo());
                if (DateUtil.getDate(user.getGmtCreate(), DatePattern.NORM_DATE_PATTERN).equals(DateUtil.getDate(o.getPaidDate()))) {
                    adjustService.asyncTraceEvent(AdjustEventDefType.D0_Purchase_People, params);
                }
            }
        });
    }


    private void orderFilter(List<TOrderDto> orderList, List<String> existsOrderNos) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }
        //使用迭代器的删除方法删除
        orderList.removeIf(order -> existsOrderNos.contains(order.getOrderNo()));

    }

    private void userFilter(List<TOrderDto> orderList, List<String> existsUsers) {
        if (CollectionUtils.isEmpty(orderList)) {
            return;
        }
        //使用迭代器的删除方法删除
        orderList.removeIf(order -> existsUsers.contains(order.getUserCode()));

    }


    private List<String> getOderNoList(Integer hour, String eventName) {
        final List<UserTaskDetailEntity> userTaskList = userTaskDetailDao.listPaidOrders(hour, eventName);
        if (CollectionUtils.isEmpty(userTaskList)) {
            return Lists.newArrayList();
        }
        return userTaskList.parallelStream().map(o -> {
            if (o == null || StringUtils.isBlank(o.getRequest())) {
                return Strings.EMPTY;
            }
            final JSONObject request = JSONObject.parseObject(o.getRequest());
            if(request.containsKey("orderNo")) {
                return request.getString("orderNo");
            }
            return Strings.EMPTY;
        }).collect(Collectors.toList());
    }

    private List<String> getUserCodeList(Integer hour, String eventName) {
        final List<UserTaskDetailEntity> userTaskList = userTaskDetailDao.listPaidOrders(hour, eventName);
        if (CollectionUtils.isEmpty(userTaskList)) {
            return Lists.newArrayList();
        }
        return userTaskList.parallelStream().map(o -> {
            if (o == null || StringUtils.isBlank(o.getRequest())) {
                return Strings.EMPTY;
            }
            final JSONObject request = JSONObject.parseObject(o.getRequest());
            if(request.containsKey("userCode")) {
                return request.getString("userCode");
            }
            return Strings.EMPTY;
        }).collect(Collectors.toList());
    }


    private void pushToAdjust() {
        final List<UserTaskDetailEntity> waitingProcessTasks = userTaskDetailDao.queryNeedProcessJobsByType(TaskTypeEnum.PUSH_DATA_TO_AD_JUST.getCode(), 5);
        if (CollectionUtils.isEmpty(waitingProcessTasks)) {
            return;
        }
        for (UserTaskDetailEntity task : waitingProcessTasks) {
            logger.info("pushToAdjustRetryTaskStart===, task:{}", JSONObject.toJSONString(task));
            Integer status = task.getStatus();
            try {
                final String result = LittleOrangeService.postForm(task.getCallbackUrl(), "e85aefe121692886acb0b2c6c4bee449");
                if (StringUtils.isNotEmpty(result)) {
                    final JSONObject resultJson = JSONObject.parseObject(result);
                    if (resultJson.containsKey("status") && "OK".equals(resultJson.getString("status"))) {
                        status = 1;
                    }
                }
                userTaskDetailDao.updateTask(task.getId(), status, result);
                logger.info("pushToAdjustRetryTaskEnd===, task:{}, result:{}", JSONObject.toJSONString(task), result);

            } catch (Exception e) {
                userTaskDetailDao.updateTask(task.getId(), status, e.getMessage());
                logger.error("pushToAdjustRetryTaskError, task:{}", JSONObject.toJSONString(task), e);
            }
        }
    }



    public static void main(String[] args) throws Exception {

//        final String result = LittleOrangeService.postForm("https://s2s.adjust.com/event?s2s=1&app_token=o7c4dqoa1q0w&event_token=e9xxm7&adid=af44a0693adb5be4f840fea51e3cd45f&created_at_unix=1705371851&environment=sandbox", "e85aefe121692886acb0b2c6c4bee449");
//        System.out.println("===" + result);
    }


}